from django.db.models import Q, Count, Avg
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, redirect

from django.views.generic import DetailView, ListView, CreateView, DeleteView, TemplateView

from django.contrib import messages
from .models import TouristAttraction, ScenicCategory, SentimentComment
from .forms import AttractionSearchForm, AttractionFilterForm, CommentForm, ReplyForm

from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy

# views.py
from django.views.generic import ListView
from django.db.models import Count, Avg, Q
from .models import TouristAttraction, ScenicCategory


class AttractionListView(ListView):
    model = TouristAttraction
    template_name = 'main/attraction_list.html'
    context_object_name = 'attractions'
    paginate_by = 9
    ordering = ['-heat_index', '-created_at']

    def get_queryset(self):
        # 只显示已发布的景点
        queryset = super().get_queryset().filter(
            status='published'
        )

        # 只对真正的外键字段使用 select_related
        # 根据错误信息，只有 created_by 是外键
        queryset = queryset.select_related('created_by')

        # 对于 categories 这样的多对多字段，使用 prefetch_related
        if hasattr(self.model, 'categories'):
            queryset = queryset.prefetch_related('categories')

        # 搜索功能
        search_query = self.request.GET.get('q')
        if search_query:
            search_filters = Q(name__icontains=search_query) | Q(description__icontains=search_query)

            # 根据实际字段添加搜索条件
            if hasattr(self.model, 'location'):
                search_filters |= Q(location__icontains=search_query)

            queryset = queryset.filter(search_filters)

        # 分类筛选
        category_id = self.request.GET.get('category')
        if category_id and hasattr(self.model, 'categories'):
            queryset = queryset.filter(categories__id=category_id)

        return queryset.distinct()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # 获取热门分类
        if hasattr(self.model, 'categories'):
            context['hot_categories'] = ScenicCategory.objects.annotate(
                attraction_count=Count('touristattraction')
            ).order_by('-attraction_count')[:8]
        else:
            context['hot_categories'] = []

        context['current_category'] = self.request.GET.get('category')

        return context


class AttractionDetailView(DetailView):
    """景点详情视图"""
    model = TouristAttraction
    template_name = 'main/attraction_detail.html'
    context_object_name = 'attraction'

    def get_queryset(self):
        return TouristAttraction.objects.filter(status='published')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        attraction = self.object

        try:
            # 添加评论表单
            context['comment_form'] = CommentForm()

            # 获取根评论
            from .models import SentimentComment
            context['root_comments'] = SentimentComment.objects.filter(
                attraction=attraction,
                is_active=True,
                parent__isnull=True
            ).select_related('author').prefetch_related('replies').order_by('-created_at')

            # 用户收藏状态
            if self.request.user.is_authenticated:
                context['user_has_collected'] = attraction.collects.filter(user=self.request.user).exists()
            else:
                context['user_has_collected'] = False

            # 情感统计 - 安全处理
            review_count = getattr(attraction, 'review_count', 0) or 0
            positive_count = getattr(attraction, 'positive_count', 0) or 0
            neutral_count = getattr(attraction, 'neutral_count', 0) or 0
            negative_count = getattr(attraction, 'negative_count', 0) or 0

            context['sentiment_stats'] = {
                'positive_percent': round((positive_count / review_count * 100), 1) if review_count > 0 else 0,
                'neutral_percent': round((neutral_count / review_count * 100), 1) if review_count > 0 else 0,
                'negative_percent': round((negative_count / review_count * 100), 1) if review_count > 0 else 0,
            }

            # 情感排名信息 - 安全处理
            from .sentiment_utils import get_sentiment_ranking, calculate_comprehensive_sentiment_score

            ranking_info = get_sentiment_ranking(attraction) or {}
            context.update(ranking_info)

            # 综合情感得分
            context['comprehensive_score'] = calculate_comprehensive_sentiment_score(attraction) or 0

            # 判断是否为情感最佳景点（前10%）
            current_rank = ranking_info.get('current_rank')
            total_ranked = ranking_info.get('total_ranked')

            # 安全处理排名比较
            if current_rank is not None and total_ranked is not None and total_ranked > 0:
                best_threshold = max(1, int(total_ranked * 0.1))
                context['is_sentiment_best'] = current_rank <= best_threshold
            else:
                context['is_sentiment_best'] = False

        except Exception as e:
            # 错误处理：设置默认值
            print(f"Error in get_context_data: {e}")
            context.setdefault('comment_form', CommentForm())
            context.setdefault('root_comments', [])
            context.setdefault('user_has_collected', False)
            context.setdefault('sentiment_stats', {
                'positive_percent': 0,
                'neutral_percent': 0,
                'negative_percent': 0
            })
            context.setdefault('is_sentiment_best', False)
            context.setdefault('comprehensive_score', 0)

        return context


class SentimentBestAttractionsView(ListView):
    """情感最佳景点排行榜"""
    model = TouristAttraction
    template_name = 'main/sentiment_best.html'
    context_object_name = 'best_attractions'
    paginate_by = 10

    def get_queryset(self):
        from .sentiment_utils import calculate_comprehensive_sentiment_score, get_positive_ratio

        # 获取有足够评论的景点
        attractions = TouristAttraction.objects.filter(
            status='published',
            review_count__gte=10  # 至少10条评论
        ).annotate(
            avg_sentiment=Avg('sentiment_comments__sentiment_score'),
            total_comments=Count('sentiment_comments')
        ).exclude(avg_sentiment__isnull=True)

        # 计算综合得分并排序
        scored_attractions = []
        for attraction in attractions:
            score = calculate_comprehensive_sentiment_score(attraction)
            positive_ratio = get_positive_ratio(attraction)

            scored_attractions.append({
                'attraction': attraction,
                'comprehensive_score': round(score, 1),
                'rank_data': {
                    'avg_sentiment': round(attraction.avg_sentiment, 2),
                    'positive_ratio': round(positive_ratio, 1),
                    'review_count': attraction.review_count
                }
            })

        # 按综合得分排序
        return sorted(scored_attractions, key=lambda x: x['comprehensive_score'], reverse=True)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['page_title'] = '情感最佳景点排行榜'
        context['total_attractions'] = len(self.get_queryset())
        return context


class AttractionByCategoryView(ListView):
    """按分类显示景点视图"""
    model = TouristAttraction
    template_name = 'main/attraction_category.html'
    context_object_name = 'attractions'
    paginate_by = 12

    def get_queryset(self):
        self.category = get_object_or_404(ScenicCategory, id=self.kwargs['category_id'])
        return TouristAttraction.objects.filter(
            categories=self.category,
            status='published'
        ).order_by('-heat_index')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['category'] = self.category
        context['categories'] = ScenicCategory.objects.all()
        return context


class SentimentAnalysisView(TemplateView):
    """情感分析页面视图"""
    template_name = 'main/sentiment_analysis.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        attractions = TouristAttraction.objects.filter(status='published')

        # 总体情感分布 - 使用景点模型中的统计字段
        total_positive = sum(attr.positive_count for attr in attractions)
        total_neutral = sum(attr.neutral_count for attr in attractions)
        total_negative = sum(attr.negative_count for attr in attractions)
        total_reviews = total_positive + total_neutral + total_negative

        # 情感百分比
        if total_reviews > 0:
            context['positive_percent'] = round((total_positive / total_reviews * 100), 1)
            context['neutral_percent'] = round((total_neutral / total_reviews * 100), 1)
            context['negative_percent'] = round((total_negative / total_reviews * 100), 1)
        else:
            context['positive_percent'] = context['neutral_percent'] = context['negative_percent'] = 0

        # 热门景点（按热度排序）
        context['hot_attractions'] = attractions.order_by('-heat_index')[:10]

        # 情感最佳景点
        from .sentiment_utils import calculate_comprehensive_sentiment_score

        best_attractions = []
        for attraction in attractions.filter(review_count__gte=5):
            if attraction.avg_sentiment_score:  # 确保有情感数据
                score = calculate_comprehensive_sentiment_score(attraction)
                best_attractions.append({
                    'attraction': attraction,
                    'score': round(score, 1)
                })

        # 按综合得分排序取前10
        context['best_sentiment_attractions'] = sorted(
            best_attractions,
            key=lambda x: x['score'],
            reverse=True
        )[:10]

        # 统计数据
        context.update({
            'total_positive': total_positive,
            'total_neutral': total_neutral,
            'total_negative': total_negative,
            'total_reviews': total_reviews,
            'total_attractions': attractions.count(),
        })

        # 🔥 修复：情感趋势分析（使用正确的字段名）
        context['sentiment_trends'] = self.get_sentiment_trends()

        return context

    def get_sentiment_trends(self):
        """获取情感趋势数据 - 修复版"""
        from django.utils import timezone
        from datetime import timedelta

        # 获取最近30天的评论数据
        thirty_days_ago = timezone.now() - timedelta(days=30)

        recent_comments = SentimentComment.objects.filter(
            created_at__gte=thirty_days_ago,
            is_active=True
        )

        # 🔥 修复：根据你的模型字段使用 sentiment_label 而不是 sentiment_type
        # 假设 sentiment_label 的值是 'positive', 'neutral', 'negative'
        sentiment_trends = {
            'positive': recent_comments.filter(sentiment_label='positive').count(),
            'neutral': recent_comments.filter(sentiment_label='neutral').count(),
            'negative': recent_comments.filter(sentiment_label='negative').count(),
        }

        return sentiment_trends


class HotRankView(ListView):
    """热度排行榜视图"""
    model = TouristAttraction
    template_name = 'main/hot_rank.html'
    context_object_name = 'attractions'

    def get_queryset(self):
        return TouristAttraction.objects.filter(
            status='published'
        ).order_by('-heat_index')[:20]

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['rank_title'] = '景点热度排行榜'
        return context


class AttractionSearchView(ListView):
    """搜索页面视图"""
    model = TouristAttraction
    template_name = 'main/attraction_search.html'
    context_object_name = 'attractions'
    paginate_by = 12

    def get_queryset(self):
        queryset = TouristAttraction.objects.filter(status='published')

        query = self.request.GET.get('q', '').strip()
        if query:
            queryset = queryset.filter(
                Q(name__icontains=query) |
                Q(description__icontains=query) |
                Q(location__icontains=query) |
                Q(city__icontains=query)
            ).distinct().order_by('-heat_index')

        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['query'] = self.request.GET.get('q', '')
        context['search_count'] = self.get_queryset().count()
        return context


class CommentCreateView(LoginRequiredMixin, CreateView):
    model = SentimentComment
    form_class = CommentForm
    template_name = 'main/attraction_detail.html'

    def form_valid(self, form):
        attraction_id = self.kwargs.get('attraction_id')
        attraction = get_object_or_404(TouristAttraction, pk=attraction_id, status='published')

        # 设置评论的关联对象
        form.instance.attraction = attraction
        form.instance.author = self.request.user

        response = super().form_valid(form)
        messages.success(self.request, '评论发表成功！')

        # 处理AJAX请求
        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': True,
                'message': '评论发表成功！'
            })

        return response

    def form_invalid(self, form):
        """处理表单验证失败"""
        messages.error(self.request, '评论发表失败，请检查表单内容。')
        print("表单错误:", form.errors)  # 调试信息

        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'errors': form.errors
            })

        # 重定向回景点详情页
        attraction_id = self.kwargs.get('attraction_id')
        return redirect('main:attraction_detail', pk=attraction_id)

    def get_success_url(self):
        """确保返回正确的URL"""
        attraction_id = self.kwargs.get('attraction_id')
        if attraction_id:
            return reverse_lazy('main:attraction_detail', kwargs={'pk': attraction_id})
        return reverse_lazy('main:index')


class ReplyCreateView(LoginRequiredMixin, CreateView):
    """回复评论视图"""
    model = SentimentComment
    form_class = ReplyForm
    template_name = 'main/reply_comment.html'

    def form_valid(self, form):
        parent_comment = get_object_or_404(SentimentComment, id=self.kwargs['comment_id'], is_active=True)
        form.instance.attraction = parent_comment.attraction
        form.instance.author = self.request.user
        form.instance.parent = parent_comment
        form.instance.source_platform = 'website'

        response = super().form_valid(form)
        messages.success(self.request, '回复成功！')

        if self.request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({'success': True})

        return response

    def get_success_url(self):
        parent_comment = get_object_or_404(SentimentComment, id=self.kwargs['comment_id'])
        return reverse_lazy('main:attraction_detail', kwargs={'pk': parent_comment.attraction.id})

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['parent_comment'] = get_object_or_404(SentimentComment, id=self.kwargs['comment_id'])
        return context


class CommentDeleteView(LoginRequiredMixin, DeleteView):
    """评论删除视图"""
    model = SentimentComment
    template_name = 'main/comment_confirm_delete.html'

    def get_queryset(self):
        queryset = super().get_queryset()
        if not self.request.user.is_staff:
            queryset = queryset.filter(author=self.request.user)
        return queryset

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        attraction_id = self.object.attraction.id

        # 软删除：将评论标记为无效
        self.object.is_active = False
        self.object.save()

        # 更新景点的情感统计
        self.object.attraction.update_sentiment_stats()

        messages.success(request, '评论已删除！')

        if request.headers.get('x-requested-with') == 'XMLHttpRequest':
            return JsonResponse({'success': True})

        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse_lazy('main:attraction_detail', kwargs={'pk': self.object.attraction.pk})
